/*
 * $Id: PDFAnnot.java,v 1.2 2007/08/26 18:56:35 gil1 Exp $ $Date: 2007/08/26
 * 18:56:35 $ This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of the License,
 * or (at your option) any later version. This library is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
 * the GNU Lesser General Public License for more details. You should have
 * received a copy of the GNU Lesser General Public License along with this
 * library; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 */
package pdf.handler;

import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;

/**
 * <p>
 * This class defines an annotation (commonly known as a Bookmark).
 * </p>
 * 
 * @author Eric Z. Beard, ericzbeard@hotmail.com
 * @author Peter T Mount, http://www.retep.org.uk/pdf/
 * @version $Revision: 1.2 $, $Date: 2007/08/26 18:56:35 $
 */
public class PDFAnnot extends PDFObject implements Serializable
{
   /*
    * NOTE: The original class is the work of Peter T. Mount, who released it
    * in the uk.org.retep.pdf package. It was modified by Eric Z. Beard as
    * follows: the package name was changed to gnu.pdf. It is still licensed
    * under the LGPL.
    */

   /**
    * The border is drawn in a beveled style (faux three-dimensional) such that
    * it looks as if it is pushed out of the page (opposite of INSET)
    */
   public static final short BEVELED = 2;

   /**
    * The border is drawn with a dashed line.
    */
   public static final short DASHED = 1;

   /**
    * flag used to indicate that the destination should fit the screen
    */
   private static final int FULL_PAGE = -9999;

   /**
    * The border is drawn in an inset style (faux three-dimensional) such that
    * it looks as if it is inset into the page (opposite of BEVELED)
    */
   public static final short INSET = 3;

   /**
    * 
    */
   private static final long serialVersionUID = 1L;

   /**
    * Solid border. The border is drawn as a solid line.
    */
   public static final short SOLID = 0;

   /**
    * The border is drawn as a line on the bottom of the annotation rectangle
    */
   public static final short UNDERLINED = 4;

   /**
    * the border for this annotation
    */
   private PDFBorder border;

   /**
    * Link to the Destination page
    */
   private PDFObject dest;

   /**
    * If fl!=FULL_PAGE then this is the region of the destination page shown.
    * Otherwise they are ignored.
    */
   private int fl, fb, fr, ft;

   /**
    * The size of the annotation
    */
   private int l, b, r, t;

   /**
    * The text of a text annotation
    */
   private String s;

   /**
    * The subtype of the outline, ie text, note, etc
    */
   private String subtype;

   /**
    * Creates a link annotation
    * 
    * @param l
    *            Left coordinate
    * @param b
    *            Bottom coordinate
    * @param r
    *            Right coordinate
    * @param t
    *            Top coordinate
    * @param dest
    *            Destination for this link. The page will fit the display.
    */
   public PDFAnnot(int l, int b, int r, int t, PDFObject dest)
   {
      this("/Link", l, b, r, t);
      this.dest = dest;
      this.fl = FULL_PAGE; // this is used to indicate a full page
   }

   /**
    * Creates a link annotation
    * 
    * @param l
    *            Left coordinate
    * @param b
    *            Bottom coordinate
    * @param r
    *            Right coordinate
    * @param t
    *            Top coordinate
    * @param dest
    *            Destination for this link
    * @param fl
    *            Left coordinate
    * @param fb
    *            Bottom coordinate
    * @param fr
    *            Right coordinate
    * @param ft
    *            Top coordinate <br>
    * <br>
    *            Rectangle describing what part of the page to be displayed
    *            (must be in User Coordinates)
    */
   public PDFAnnot(int l, int b, int r, int t,
         PDFObject dest,
         int fl, int fb, int fr, int ft)
   {
      this("/Link", l, b, r, t);
      this.dest = dest;
      this.fl = fl;
      this.fb = fb;
      this.fr = fr;
      this.ft = ft;
   }

   /**
    * Creates a text annotation
    * 
    * @param l
    *            Left coordinate
    * @param b
    *            Bottom coordinate
    * @param r
    *            Right coordinate
    * @param t
    *            Top coordinate
    * @param s
    *            Text for this annotation
    */
   public PDFAnnot(int l, int b, int r, int t, String s)
   {
      this("/Text", l, b, r, t);
      this.s = s;
   }

   /**
    * This is used to create an annotation.
    * 
    * @param s
    *            Subtype for this annotation
    * @param l
    *            Left coordinate
    * @param b
    *            Bottom coordinate
    * @param r
    *            Right coordinate
    * @param t
    *            Top coordinate
    */
   protected PDFAnnot(String s, int l, int b, int r, int t)
   {
      super("/Annot");
      subtype = s;
      this.l = l;
      this.b = b;
      this.r = r;
      this.t = t;
   }

   /**
    * Sets the border for the annotation. Unlike the other method, this
    * produces a dashed border.
    * <p>
    * Important: the annotation must have been added to the document before
    * this is used. If the annotation was created using the methods in PDFPage,
    * then the annotation is already in the document.
    * 
    * @param width
    *            Width of the border
    * @param dash
    *            Array of lengths, used for drawing the dashes. If this is
    *            null, then the default of {3} is used.
    */
   public void setBorder(double width, double dash[])
   {
      border = new PDFBorder(width, dash);
      pdfDocument.add(border);
   }

   /**
    * Sets the border for the annotation. By default, no border is defined.
    * <p>
    * If the style is DASHED, then this method uses PDF's default dash scheme
    * {3}
    * <p>
    * Important: the annotation must have been added to the document before
    * this is used. If the annotation was created using the methods in PDFPage,
    * then the annotation is already in the document.
    * 
    * @param style
    *            Border style SOLID, DASHED, BEVELED, INSET or UNDERLINED.
    * @param width
    *            Width of the border
    */
   public void setBorder(short style, double width)
   {
      border = new PDFBorder(style, width);
      pdfDocument.add(border);
   }

   /**
    * Should this be public??
    * 
    * @param os
    *            OutputStream to send the object to
    * @exception IOException
    *                on error
    */
   @Override
   public void write(OutputStream os) throws IOException
   {
      // Write the object header
      writeStart(os);

      // now the objects body
      os.write("/Subtype ".getBytes());
      os.write(subtype.getBytes());
      os.write("\n/Rect [".getBytes());
      os.write(Integer.toString(l).getBytes());
      os.write(" ".getBytes());
      os.write(Integer.toString(b).getBytes());
      os.write(" ".getBytes());
      os.write(Integer.toString(r).getBytes());
      os.write(" ".getBytes());
      os.write(Integer.toString(t).getBytes());
      os.write("]\n".getBytes());

      // handle the border
      if (border == null)
         os.write("/Border [0 0 0]\n".getBytes());
      // if(pdf.defaultOutlineBorder==null)
      // pdf.add(pdf.defaultOutlineBorder = new border(SOLID,0.0));
      // os.write(pdf.defaultOutlineBorder.toString().getBytes());
      else
      {
         os.write("/BS ".getBytes());
         os.write(border.toString().getBytes());
         os.write("\n".getBytes());
      }

      // Now the annotation subtypes
      if (subtype.equals("/Text"))
      {
         os.write("/Contents ".getBytes());
         os.write(PDFStringHelper.makePDFString(s).getBytes());
         os.write("\n".getBytes());
      }
      else if (subtype.equals("/Link"))
      {
         os.write("/Dest [".getBytes());
         os.write(dest.toString().getBytes());
         if (fl == FULL_PAGE)
            os.write(" /Fit]".getBytes());
         else
         {
            os.write(" /FitR ".getBytes());
            os.write(Integer.toString(fl).getBytes());
            os.write(" ".getBytes());
            os.write(Integer.toString(fb).getBytes());
            os.write(" ".getBytes());
            os.write(Integer.toString(fr).getBytes());
            os.write(" ".getBytes());
            os.write(Integer.toString(ft).getBytes());
            os.write("]".getBytes());
         }
         os.write("\n".getBytes());
      }

      // finish off with its footer
      writeEnd(os);
   }
}
